<template>
  <el-form
    ref="formRef"
    :model="form"
    :rules="rules"
    :label-width="formAttr.labelWidth"
    :inline="formAttr.inline"
    :label-position="formAttr.labelPosition"
    :hide-required-asterisk="formAttr.hideRequiredAsterisk"
    :show-message="formAttr.showMessage"
    :inline-message="formAttr.inlineMessage"
    :disabled="formAttr.disabled"
  >
    <el-row :gutter="col.gutter">
      <template v-for="(item, index) in formItems">
        <el-col :xs="item.col.xs" :sm="item.col.sm" :md="item.col.md" :key="index" v-if="!item.hidden">
          <el-form-item
            :label-width="item.hideLabel?'0px':(item.labelWidth?item.labelWidth:formAttr.labelWidth)"
            :label="item.title || ''"
            :prop="item.field || ''"
            :size="item.size || formAttr.size"
          >
            <slot :name="item.slot" v-if="item.slot" :item="item"></slot>
            <item
              v-else
              :attr="{...item.prop,disabled:!!item.disabled}"
              :group="item.group"
              :field="item.field"
              :form-value="form[item.field]"
              @changeData="(e)=>changeData(e,item)"
            />
          </el-form-item>
        </el-col>
      </template>
    </el-row>

    <slot name="btn">
      <div class="text-center">
        <el-button type="primary" @click="handleSubmit" :loading="submitting">确 定</el-button>
        <el-button @click="handleCancel">取 消</el-button>
      </div>
    </slot>
  </el-form>
</template>

<script>
import Item from "./item"

export default {
  name: "BaseForm",
  components: {Item},
  data() {
    return {
      formAttr: {
        labelPosition: 'right',
        labelWidth: '100px',
        inline: false, // 行内表单模式
        size: 'medium', // 用于控制该表单内组件的尺寸 medium / small / mini
        hideRequiredAsterisk: false, // 是否隐藏必填字段的标签旁边的红色星号
        showMessage: true, // 是否显示校验错误信息
        inlineMessage: false, // 是否以行内形式展示校验信息
        disabled: false, // 是否禁用该表单内的所有组件。若设置为 true，则表单内组件上的 disabled 属性不再生效
      },
      col: {
        xs: 24,
        sm: 24,
        md: 24,
        gutter: 15
      },
      formItems: [],
      form: {},
      defaultForm: {},
      rules: {},
      submitting: false,
    }
  },
  methods: {
    initData(formData = {}) {
      formData.form = formData.form || {}
      formData.rules = formData.rules || {}
      formData.formAttr = formData.formAttr || {}
      formData.col = formData.col || {}
      formData.formItems = formData.formItems || []

      this.formAttr = this.$common.copyObject(this.formAttr, formData.formAttr)
      this.col = Object.assign(this.col, formData.col)
      this.rules = formData.rules
      this.form = formData.form

      formData.formItems.map(item => {
        if (item.col && JSON.stringify(item.col) !== '{}') {
          item.col.xs = item.col.xs ? item.col.xs : this.col.xs
          item.col.sm = item.col.sm ? item.col.sm : item.col.xs
          item.col.md = item.col.md ? item.col.md : item.col.sm
        } else {
          item.col = this.col
        }
        if(item.col.sm < item.col.md) item.col.sm = item.col.md
        if(item.col.xs < item.col.sm) item.col.xs = item.col.sm
      })
      this.formItems = formData.formItems
      this.defaultForm = JSON.parse(JSON.stringify(this.form))
    },
    changeData(data, item) {
      let event = data?.event || ''
      if (event === 'change') {
        this.form[data.key] = data.value
        if (item.onChange && typeof item.onChange === 'function') item.onChange(data.value, 'change')
      } else {
        if (item.event && typeof item.event === 'function') item.event(data)
      }
      this.$forceUpdate()
    },
    validateForm() {
      return new Promise((resolve, reject) => {
        this.$refs['formRef'].validate((valid, fields) => {
          if (valid) {
            resolve(JSON.parse(JSON.stringify(this.form)))
          } else {
            reject('validate form', fields)
          }
        })
      })
    },
    resetForm() {
      this.$refs['formRef'].resetFields()
      this.$emit("reset", this.form)
    },
    validateClear() {
      this.$refs['formRef'].clearValidate()
    },
    async handleSubmit() {
      try {
       let data = await this.validateForm()
       this.$emit('submit',data)
      }catch (e) {}
    },
    handleCancel() {
      this.$refs['formRef'].resetFields()
      this.$refs['formRef'].clearValidate()
      this.$emit('close')
    }
  }
}
</script>

<style scoped>

</style>
